---
title: Release Process
sidebar_position: 40
---

:::info

This section needs a lot of love and automation 🙂

:::

### Prerequisites
1. Make sure your GPG is available on GitHub at `https://github.com/<username>.gpg`. This can be added at https://github.com/settings/keys.
    -  If you haven't already, open a PR to add your GPG key to the [`KEYS`](https://github.com/oras-project/oras/blob/main/KEYS) file (see file for instructions).
1. Open a bump PR to build with the latest golang: replace go version of the [binary](https://github.com/oras-project/oras/blob/main/.github/workflows/release-github.yml#L32) and [image](https://github.com/oras-project/oras/blob/main/Dockerfile#L14) to match the latest stable version. Skippable if the latest version is already used.
1. (patch-release-only) Cherry-pick or backport the fix commits to the patch release branch. Make sure applicable critical and high CVE patches are on the release branch.

### Request to vote and merge
1. Open a PR to update the `oras` version: replace the [current version](https://github.com/oras-project/oras/blob/main/internal/version/version.go#L20) with the upcoming release version.
    - The target branch is:
        - `main` if releasing a new version.
        - `release-<major>.<minor>` if releasing a patch.
    - The title should be `bump: tag and release ORAS CLI v<major>.<minor>.<patch>[-<pre-release>]`.
    - The description must reference the digest of version bump up commit for voting.
1. Send a message to the ORAS slack channel to call for a vote on the release PR.
    - The target commit should be the SHA digest of the last commit in the release PR
1. If the vote PR has a super-majority of approval from ORAS maintainers, then the PR could be merged into the target branch.
    - Make sure that
        - the PR is merged with `Create a merge commit` option.
        - the merge commit title should be generated by GitHub.
        - the merge commit message should be the signoff info.
1. (optional) Cut off a release branch named `release-<major>.<minor>` on the tagged commit **ONLY** when releasing a new minor version.

### Release
1. Make a fresh clone of the [repository](https://github.com/oras-project/oras) after all above steps are completed. Create a new tag for the version prefixed with "v" and push the tag directly to the repository. The tag should be created on the voted commit, **NOT** the merge commit.
    ```sh
    version=1.0.0
    digest=b58e7b910ca556973d111e9bd734a71baef03db2 # replace with the digest of the voted commit
    git tag v${version} $digest
    ```
    After validating the tag is created on the voted commit, push the created tag:
    ```sh
    git push origin v${version}
    ```
1. Wait for GitHub Actions to complete successfully for both the `release-ghcr` and `release-github` pipelines.
1. Download all of the artifacts uploaded to the new GitHub release locally (`*checksums.txt`, `*darwin_amd64.tar.gz`, `*linux_armv7.tar.gz`, `*linux_arm64.tar.gz`, `*linux_amd64.tar.gz`, `*windows_amd64.zip`).
1. Verify the checksum of the file, downloaded platform should pass the check:
    ```sh
    shasum -c oras_${version}_checksums.txt
    ```
1. Run `oras version` command and make sure that version number and git commit digest is the expected value (same as the commit used to create the tag). Example:
    ```sh
    mkdir -p oras-bin/
    tar -zxf oras_${version}_linux_amd64.tar.gz -C oras-bin
    ./oras-bin/oras version
    ```

1. After validation, remove the temporary oras-bin directory:
    ```sh
    rm -rf oras-bin/
    ```

1. Create armored GPG signatures(`.asc`) using the key in the `KEYS` file.
    ```sh
    for file in `ls`; do
        gpg --armor --detach-sign $file
    done
    ```
1. Validate the signatures. Note that the `KEYS` file should be imported with `gpg --import KEYS`. Run some form of the following (adapted from Linux project):
    ```sh
    for file in `ls *.asc`; do
        echo "Verifying: $file"
        if gpg --verify "$file"; then
            echo "✅ Good signature for $file"
        else
            echo "❌ BAD signature for $file"
        fi
        echo "----------------------------------------"
    done
    ```
1. Click the "Edit release" button on the release, and add the `.asc` files created in the previous step. Edit the release description to include change logs and a note indicating the releaser's GPG key used to sign the artifacts. See an example:
    ```
    ## Notes

    This release was signed with `46D3 369B 393F 6F82 71FD 1CE8 F86E C70D 2B0C 404F` (@qweeah's GPG key) which can be found [here](https://github.com/qweeah.gpg).
    ```
    The uploaded signatures and GPG key will be used for [binary validation](https://oras.land/docs/how_to_guides/verifying_binaries).
1. Check the new draft release, revise the release notes.
1. Click "Publish Release" button to save. Double-check that the release contains a corresponding `.asc` file for each release artifact.

### Update user documentation

Update the necessary documentation in the ORAS-WWW repository to reflect the changes of the release on the ORAS website, includes but not limited to installation guide, user guide, banner, release blog.

### Announce the new release

Announce the new release in the ORAS Slack channel and send gratitude to contributors.

### Updating package managers (only suggested for stable releases)
#### Snap
1. Go to https://github.com/oras-project/oras/actions/workflows/release-snap.yml
1. Click on the top right drop-down `Run workflow`
  - Select a branch or tag to run the release. **This is not the actual to-be-released version** but only configuration of GitHub actions and Snapcraft.
  - Enter the release version. **The version should start with a `v`**.
  - (optional) If the target version is stable, check the stable release checkbox.
  - Click `Run workflow`.

### Library vs Utility

oras actually serves 2 purposes: library and utility. All of the above steps, except for the tag, are entirely about the utility.

For better or for worse, semver is tied up with both. As an example, the current issue with the go modules solely affects its inclusion as a library, but it is immediate. It can be fixed by cutting v1.0.0, and the downstream problems go away. yet cutting a release _also_ means all of the above, which are far more complicated.